package com.dng.book.util;

import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * Redis操作工具类
 * 
 * @author dng
 * @since 2024-01-01
 */
@Slf4j
@Component
public class RedisUtil {

    @Resource
    private RedisTemplate<String, String> redisTemplate;

    /**
     * 设置缓存
     * 
     * @param key   键
     * @param value 值
     * @return 是否成功
     */
    public boolean set(String key, String value) {
        try {
            redisTemplate.opsForValue().set(key, value);
            log.debug("Redis设置成功: key={}, value={}", key, value);
            return true;
        } catch (Exception e) {
            log.error("Redis设置失败: key={}, value={}, error={}", key, value, e.getMessage());
            return false;
        }
    }

    /**
     * 设置缓存并设置过期时间
     * 
     * @param key     键
     * @param value   值
     * @param timeout 过期时间
     * @param unit    时间单位
     * @return 是否成功
     */
    public boolean set(String key, String value, long timeout, TimeUnit unit) {
        try {
            redisTemplate.opsForValue().set(key, value, timeout, unit);
            log.debug("Redis设置成功: key={}, value={}, timeout={}, unit={}", key, value, timeout, unit);
            return true;
        } catch (Exception e) {
            log.error("Redis设置失败: key={}, value={}, timeout={}, unit={}, error={}", key, value, timeout, unit, e.getMessage());
            return false;
        }
    }

    /**
     * 获取缓存
     * 
     * @param key 键
     * @return 值
     */
    public String get(String key) {
        try {
            String value = redisTemplate.opsForValue().get(key);
            log.debug("Redis获取: key={}, value={}", key, value);
            return value;
        } catch (Exception e) {
            log.error("Redis获取失败: key={}, error={}", key, e.getMessage());
            return null;
        }
    }

    /**
     * 删除缓存
     * 
     * @param key 键
     * @return 是否成功
     */
    public boolean delete(String key) {
        try {
            Boolean result = redisTemplate.delete(key);
            log.debug("Redis删除: key={}, result={}", key, result);
            return result != null && result;
        } catch (Exception e) {
            log.error("Redis删除失败: key={}, error={}", key, e.getMessage());
            return false;
        }
    }

    /**
     * 判断key是否存在
     * 
     * @param key 键
     * @return 是否存在
     */
    public boolean hasKey(String key) {
        try {
            Boolean result = redisTemplate.hasKey(key);
            log.debug("Redis检查key存在: key={}, result={}", key, result);
            return result != null && result;
        } catch (Exception e) {
            log.error("Redis检查key存在失败: key={}, error={}", key, e.getMessage());
            return false;
        }
    }

    /**
     * 设置过期时间
     * 
     * @param key     键
     * @param timeout 过期时间
     * @param unit    时间单位
     * @return 是否成功
     */
    public boolean expire(String key, long timeout, TimeUnit unit) {
        try {
            Boolean result = redisTemplate.expire(key, timeout, unit);
            log.debug("Redis设置过期时间: key={}, timeout={}, unit={}, result={}", key, timeout, unit, result);
            return result != null && result;
        } catch (Exception e) {
            log.error("Redis设置过期时间失败: key={}, timeout={}, unit={}, error={}", key, timeout, unit, e.getMessage());
            return false;
        }
    }

    /**
     * 获取过期时间
     * 
     * @param key 键
     * @return 过期时间（秒）
     */
    public long getExpire(String key) {
        try {
            Long expire = redisTemplate.getExpire(key);
            log.debug("Redis获取过期时间: key={}, expire={}", key, expire);
            return expire != null ? expire : -1;
        } catch (Exception e) {
            log.error("Redis获取过期时间失败: key={}, error={}", key, e.getMessage());
            return -1;
        }
    }

    /**
     * 根据模式获取所有匹配的key
     * 
     * @param pattern 模式
     * @return key集合
     */
    public Set<String> keys(String pattern) {
        try {
            Set<String> keys = redisTemplate.keys(pattern);
            log.debug("Redis获取匹配key: pattern={}, keys={}", pattern, keys);
            return keys;
        } catch (Exception e) {
            log.error("Redis获取匹配key失败: pattern={}, error={}", pattern, e.getMessage());
            return null;
        }
    }

    /**
     * 测试Redis连接
     * 
     * @return 是否连接正常
     */
    public boolean testConnection() {
        try {
            String testKey = "test_connection_" + System.currentTimeMillis();
            String testValue = "test_value";
            
            // 设置测试值
            boolean setResult = set(testKey, testValue, 10, TimeUnit.SECONDS);
            if (!setResult) {
                log.error("Redis连接测试失败: 设置值失败");
                return false;
            }
            
            // 获取测试值
            String getValue = get(testKey);
            if (!testValue.equals(getValue)) {
                log.error("Redis连接测试失败: 获取值不匹配, expected={}, actual={}", testValue, getValue);
                return false;
            }
            
            // 删除测试值
            delete(testKey);
            
            log.info("Redis连接测试成功");
            return true;
        } catch (Exception e) {
            log.error("Redis连接测试失败: error={}", e.getMessage());
            return false;
        }
    }
} 